package handler

import (
	"github.com/gin-gonic/gin"
	"onvif_server/api"
	"onvif_server/api/camera"
	"onvif_server/internal/errcode"
	"onvif_server/internal/service"
	"onvif_server/internal/utils"
	"onvif_server/pkg/onvif"
)

type CameraHandler struct {
	*Handler
	cameraService service.CameraService
}

func NewCameraHandler(handler *Handler, cameraService service.CameraService) *CameraHandler {
	return &CameraHandler{
		Handler:       handler,
		cameraService: cameraService,
	}
}

func (h *CameraHandler) Create(ctx *gin.Context) {
	req := camera.CreateReq{}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.cameraService.Create(ctx, &req), nil)
}

func (h *CameraHandler) List(ctx *gin.Context) {
	req := camera.ListReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	total, items, err := h.cameraService.List(ctx, &req)
	api.PageData(ctx, total, items, err)
}

func (h *CameraHandler) Update(ctx *gin.Context) {
	req := camera.UpdateReq{}

	if err := ctx.ShouldBindJSON(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.cameraService.Update(ctx, &req), nil)
}

func (h *CameraHandler) Delete(ctx *gin.Context) {
	req := camera.DeleteReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.cameraService.Delete(ctx, req.IDs), nil)
}

func (h *CameraHandler) GetDatetime(ctx *gin.Context) {
	req := camera.IdOrDeviceIdReq{}
	if err := ctx.ShouldBind(&req); err != nil || (req.Id == 0 && req.DeviceId == "") {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	dt, err := h.cameraService.GetDatetime(ctx, &req)
	api.Response(ctx, err, dt.Format(utils.FormatDatetime))
}

func (h *CameraHandler) SyncDatetime(ctx *gin.Context) {
	req := camera.IdOrDeviceIdReq{}
	if err := ctx.ShouldBind(&req); err != nil || (req.Id == 0 && req.DeviceId == "") {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	api.Response(ctx, h.cameraService.SyncDatetime(ctx, &req), nil)
}

func (h *CameraHandler) Discovery(ctx *gin.Context) {
	res, err := h.cameraService.Discovery(ctx)
	api.Response(ctx, err, res)
}

func (h *CameraHandler) CheckConnection(ctx *gin.Context) {
	req := onvif.CameraConnection{}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.CheckConnection(ctx, &req)
	api.Response(ctx, err, res)
}

func (h *CameraHandler) GetM3u8Hour(ctx *gin.Context) {
	req := camera.GetM3u8Req{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.GetM3u8(ctx, &req, "hour")
	if err != nil {
		api.Response(ctx, err, nil)
	}
	api.Response(ctx, err, res[0])
}

func (h *CameraHandler) GetM3u8Day(ctx *gin.Context) {
	req := camera.GetM3u8Req{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.GetM3u8(ctx, &req, "day")
	api.Response(ctx, err, res)
}

// GetMp4ByImage 通过名称获取该时间段的视频
// 输入:https://img.nextstorage.cn/boxalarm/2023/4/13/3CE36B7AE4A6_2023_04_13_16_03_04.jpg
// 返回 /video/3CE36B7AE4A6/tmp/20230413160304.mp4
func (h *CameraHandler) GetMp4ByImage(ctx *gin.Context) {
	req := camera.GetMp4ByImgReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.GetMp4ByImg(ctx, &req)
	api.Response(ctx, err, res)
}

func (h *CameraHandler) GetHistory(ctx *gin.Context) {
	req := camera.GetHistoryReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.GetHistory(ctx, &req)
	api.Response(ctx, err, res)
}

func (h *CameraHandler) VideoSearch(ctx *gin.Context) {
	req := camera.VideoSearchReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.SearchVideo(ctx, &req)
	api.Response(ctx, err, res)
}

func (h *CameraHandler) GetSnapUrl(ctx *gin.Context) {
	req := camera.GetSnapUrlReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		api.Fail(ctx, errcode.ErrInvalidParams.Wrap(err))
		return
	}
	res, err := h.cameraService.GetSnapUrl(ctx, &req)
	api.Response(ctx, err, res)
}
